<template>
  <div
    :style="{
      height: !Object.keys(girdOption).length || girdOption.customHeight ? girdOption.customHeight || 'auto' : '100%',
      overflow: 'visible',
    }"
    ref="tableForm"
  >
    <!-- 表单 -->
    <a-card v-if="formItems && formItems.length" :bordered="false" class="searchCard margin-b-2">
      <a-row :style="{ alignItems: 'center', marginRight: showMore ? '158px' : '0' }">
        <a-col :flex="1">
          <a-form
            ref="form"
            :model="formData"
            :auto-label-width="true"
            :rules="rules"
            label-align="right"
            :disabled="disabled"
          >
            <a-row :gutter="16">
              <template v-for="field in formItems">
                <a-col
                  v-if="!field.hide && !field.showHide"
                  :key="field.name"
                  :xs="field.span || rowspan || 12"
                  :xl="field.span || rowspan || 8"
                >
                  <a-form-item
                    :field="field.name"
                    :label="field.label ? field.label : ''"
                    :label-col-flex="field.labelColFlex || labelColFlex || undefined"
                  >
                    <a-radio-group
                      v-if="field.type === 'a-radio'"
                      v-model="formData[field.name]"
                      @change="emit('formChange', field.name, formData[field.name])"
                    >
                      <a-radio v-for="(it, i) in field.options" :key="i" :value="it.value">{{ it.label }}</a-radio>
                    </a-radio-group>
                    <span v-else-if="field.type === 'label'">{{ formData[field.name] }}</span>
                    <slot v-else-if="field.type === 'slotItem'" name="slotItem" :field="field"></slot>
                    <a-select
                      v-else-if="field.type === 'a-select' && field.valueKey"
                      v-model="formData[field.name]"
                      :placeholder="'请选择' + field.label"
                      :multiple="field.multiple"
                      :value-key="field.valueKey"
                      :field-names="field.fieldNames"
                    >
                      <a-option
                        v-for="(it, i) of field.options"
                        :key="i"
                        :value="it"
                        :label="it[field.fieldNames ? field.fieldNames.label : 'label']"
                      />
                    </a-select>
                    <a-date-picker
                      v-else-if="field.type === 'a-date-picker'"
                      style="width: 100%"
                      format="YYYY-MM-DD"
                      @change="confirmDate"
                    />
                    <component
                      v-else
                      :is="field.type"
                      v-model="formData[field.name]"
                      :allow-clear="!(field.noClear || readonly || field.readonly)"
                      :data="field.data"
                      allow-search
                      :style="field.style"
                      :placeholder="
                        readonly || field.readonly
                          ? ''
                          : field.placeholder ||
                            (field.type === 'a-input' || field.type === 'a-textarea'
                              ? '请输入' + field.label
                              : field.type === 'a-select' || field.type === 'a-tree-select'
                              ? '请选择' + field.label
                              : field.placeholder)
                      "
                      :options="field.options"
                      :disable-filter="true"
                      :disabled="field.disabled"
                      :readonly="readonly || field.readonly"
                      :fieldNames="field.fieldNames"
                      :multiple="field.multiple"
                      :max-tag-count="field.maxTagCount || 1"
                      :max="field.max"
                      :min="field.min"
                      hide-button
                      :show-time="field.showTime"
                      :format="field.format"
                      :autoSize="field.autoSize"
                      :max-length="field.type === 'a-textarea' ? ('maxLength' in field ? field.maxLength : 100) : null"
                      :show-word-limit="field.type === 'a-textarea' ? true : false"
                      @change="emit('formChange', field.name, formData[field.name])"
                      @focus.self="emit('focus', field.name, formData[field.name])"
                      @search="
                        (val) => {
                          $emit('search', val)
                        }
                      "
                      @clear="emit('clearForm', field.name, formData[field.name])"
                      @click="emit('clickForm', field.name, formData[field.name])"
                    >
                      <template v-if="field.suffix" #suffix>
                        <span>{{ field.suffix }}</span>
                      </template>
                    </component>
                    {{ field.showTime }}
                  </a-form-item>
                </a-col>
              </template>
            </a-row>
          </a-form>
        </a-col>
      </a-row>
      <div class="searchExpand" v-if="showMore">
        <div class="searchBtn">
          <a-button type="primary" @click="searchFn">查询</a-button>
          <a-button type="outline" @click="resetFn">重置</a-button>
        </div>
        <div v-if="formItems.length > (mediaFlag ? 3 : 2)" class="expand">
          <div class="pointer" v-if="!expand" @click="expandFn()">
            <p class="margin-r-1">展开更多条件</p>
            <icon-caret-down />
          </div>
          <div class="pointer" v-if="expand" @click="expandFn()">
            <p class="margin-r-1">收起</p>
            <icon-caret-up />
          </div>
        </div>
      </div>
    </a-card>
    <!--表格  -->
    <a-card
      v-if="girdOption.columns && columns.length"
      ref="table"
      :bordered="false"
      class="table"
      :body-style="{
        height: girdOption.customHeight === 'auto' ? 'auto' : topHeight + 'px',
        boxSizing: 'border-box',
      }"
    >
      <div v-if="girdOption.btnList" class="margin-b-2 tr">
        <slot name="btnSlot"></slot>
        <BtnGroup
          v-if="Array.isArray(girdOption.btnList)"
          :btn-list="girdOption.btnList || []"
          @handleBtnClick="handleBtnClick"
        />
      </div>
      <a-table
        ref="tableRef"
        :row-key="tableId"
        :columns="columns"
        :data="pageData.tableData"
        :pagination="pageData.pagination"
        column-resizable
        :loading="girdOption.loading"
        hide-expand-button-on-empty
        :summary="girdOption.summary ? summary : false"
        summary-text="合计"
        :bordered="girdOption.bordered || true"
        v-model:selectedKeys="girdOption.selectedKeys"
        :row-selection="rowSelection"
        :scroll="{ x: 180, y: 'calc(100% - ' + (girdOption.btnList && girdOption.btnList.length ? 50 : 0) + 'px)' }"
        :span-method="girdOption.spanMethod || mergeTable"
        @select-all="selectAll"
        @pageChange="changeCurrent"
        @pageSizeChange="changePageSize"
        @selectionChange="selectionChange"
        @sorter-change="sorterChange"
        @row-click="rowclick"
        @select="select"
      >
        <!-- 序号 -->
        <template #serialNumber="{ record, rowIndex }">
          <div v-if="(girdOption.summary && !record.summaryRow) || !girdOption.summary">
            {{
              pageData.pagination
                ? pageData.pagination.pageSize * (pageData.pagination.current - 1) + ++rowIndex
                : ++rowIndex
            }}
          </div>
          <div v-else>合计</div>
        </template>
        <!-- 操作栏 -->
        <template #optional="{ record, rowIndex }">
          <div v-if="(girdOption.summary && !record.summaryRow) || !girdOption.summary" class="operate">
            <slot name="tableOptate" :record="record" :rowIndex="rowIndex" />
          </div>
        </template>
        <template
          v-for="slotItem in girdOption.tableSlotList || []"
          :key="slotItem"
          v-slot:[slotItem]="{ record, rowIndex }"
        >
          <slot :name="slotItem" :record="record" :rowIndex="rowIndex" />
        </template>
      </a-table>
    </a-card>
  </div>
</template>

<script setup>
import { toRefs, ref, nextTick, reactive, computed, watchEffect, getCurrentInstance } from 'vue'
import BtnGroup from '@/components/btnGroup/index.vue'
const { proxy } = getCurrentInstance()
const props = defineProps({
  // 表单json配置项
  formItems: {
    type: Array,
    default: () => [],
  },
  // 表单校验规则
  rules: {
    type: Object,
    default: () => {},
  },
  // 表单数据
  formData: {
    type: Object,
    default: () => {},
  },
  // 表单全局禁用
  disabled: {
    type: Boolean,
    default: false,
  },
  // 表格
  girdOption: {
    type: Object,
    default: () => ({}),
  },
  // 是否展开收起
  showMore: {
    type: Boolean,
    default: true,
  },
  rowspan: {
    type: Number,
  },
  labelColFlex: {
    type: String,
    default: '',
  }, // 表单标签宽度
  readonly: {
    type: Boolean,
    default: false,
  },
})
const { formItems, formData, girdOption, showMore } = toRefs(props)
const {
  pagination = {
    showTotal: true,
    showJumper: true,
    showPageSize: true,
  } || true, //是否开启分页
  tableId, //table唯一标识
} = girdOption.value
const emit = defineEmits([
  'handleBtnClick',
  'getTableList',
  'selectionChange',
  'select',
  'sorterChange',
  'selectAll',
  'formChange',
  'focus',
  'clearForm', //清空表单
  'clickForm', //点击表单出弹窗，避免用focus后clear不生效
  'rowclick', //点击表格
  'confirmDate', //确认时间
])
const pageTotal = ref(0)
const pageData = reactive({
  tableData: [],
  pagination: pagination
    ? {
        current: 1,
        pageSize: 10,
        ...pagination,
        total: pageTotal,
      }
    : pagination, //分页为true带所有配置否则为false不开启
})

/* start 表单*/
const expand = ref(false)
const mqList = window.matchMedia('(min-width: 1200px)') //媒体查询截取表单
const mediaFlag = ref(mqList.matches ? true : false) //标记是否超过1200
if (showMore.value) {
  // 表单展开收起
  watchEffect(() => {
    let index = mediaFlag.value ? 3 : 2
    if (formItems.value.length >= index) {
      //有展开收起时
      formItems.value.forEach((item, i) => {
        item.showHide = false
        if (index <= i) {
          item.showHide = !expand.value ? true : false
        }
      })
    }
  })
  const widthChangeCallback = (mqList) => {
    if (mqList.matches) {
      mediaFlag.value = true
    } else {
      mediaFlag.value = false
    }
  }
  widthChangeCallback(mqList)
  mqList.addEventListener('change', widthChangeCallback)
}
// 展开收起方法：控制表格高度
const expandFn = () => {
  expand.value = !expand.value
  nextTick(() => {
    if (table.value) {
      topHeight.value = tableForm.value.offsetTop + tableForm.value.offsetHeight - table.value.$el.offsetTop
    }
  })
}
// 表单查询
const searchFn = () => {
  if (pageData.pagination) {
    pageData.pagination.current = 1
  }
  emit('getTableList', pageData.pagination)
}
const form = ref() // ref绑定组件：表单
// 表单重置
const resetFn = () => {
  form.value.resetFields()
  if (pageData.pagination) {
    pageData.pagination.current = 1
  }
  emit('getTableList', pageData.pagination)
}
// 确认选择时间
const confirmDate = (dateString) => {
  emit('confirmDate', dateString)
}
/* end 表单*/

/* start 表格*/
const columns = computed(() => {
  return girdOption.value.columns.filter((item) => {
    item.ellipsis = 'ellipsis' in girdOption.value ? girdOption.value.ellipsis : true
    item.tooltip = true
    return !item.hide
  })
})
// 复选单选框判断
const rowSelection = computed(() => {
  if (girdOption.value.rowSelection === 'radio') {
    // 单选girdOption.value.rowSelection传radio
    return { type: 'radio' }
  } else if (girdOption.value.rowSelection) {
    // 复选girdOption.value.rowSelection传true
    return { type: 'checkbox', showCheckedAll: true }
  } else {
    // girdOption.value.rowSelection不传不显示
    return undefined
  }
})

const handleBtnClick = (type) => {
  emit('handleBtnClick', type)
}
// 分页切换
const changeCurrent = (pageCurrent) => {
  pageData.pagination.current = pageCurrent
  emit('getTableList', pageData.pagination)
}
const changePageSize = (pageSize) => {
  pageData.pagination.pageSize = pageSize
  emit('getTableList', pageData.pagination)
}
// 设置表格数据
const setTableData = (data, total) => {
  pageData.tableData = data
  pageTotal.value = total
}
const getTableData = () => {
  return pageData.tableData
}
// 多选
const selectionChange = (list) => {
  emit('selectionChange', list)
}
// 排序
const sorterChange = (dataIndex, direction) => {
  emit('sorterChange', dataIndex, direction)
}

// 选择
const select = (rowKeys, rowKey, record) => {
  emit('select', { rowKeys, rowKey, record })
}

// 全选
const selectAll = (checked) => {
  emit('selectAll', checked)
}

//合并相同单元格
const mergeTable = (data) => {
  if (girdOption.value.mergeColumns) {
    return proxy.$commontFn.mergeTable(data, girdOption.value.mergeColumns)
  }
}

// 合计
const summary = ({ data }) => {
  if (girdOption.value.summaryObj) {
    let obj = {}
    girdOption.value.summaryObj.forEach((it) => {
      obj[it] = 0
    })
    data.forEach((record) => {
      for (const key in obj) {
        obj[key] += record[key]
      }
    })
    for (const key in obj) {
      obj[key] = obj[key].toFixed(2)
    }
    return [{ ...obj, summaryRow: true }]
  }
}

const tableForm = ref() // ref绑定组件：整体控件
const table = ref(0) // ref绑定组件：表格
let topHeight = ref(0) // 表格高度
nextTick(() => {
  if (table.value) {
    topHeight.value = tableForm.value.offsetTop + tableForm.value.offsetHeight - table.value.$el.offsetTop
  }
})
// 行点击
const rowclick = (record) => {
  emit('rowclick', record)
}
const setPageCurrent = (val) => {
  pageData.pagination.current = val
}
defineExpose({ setTableData, getTableData, setPageCurrent })
/* end 表格*/
</script>
<style scoped lang="less">
.searchCard {
  background-color: var(--color-bg-2);
  :deep(.arco-card-body) {
    padding-bottom: 0;
  }
  .searchExpand {
    .expand {
      height: @size-8;
      > div {
        border-radius: @border-radius-medium;
        width: @size-40;
        margin: auto;
        display: flex;
        align-items: center;
        justify-content: center;
        color: @primary-6;
        > p {
          line-height: @size-default;
        }
      }
      > div:hover {
        background-color: @color-fill-2;
      }
    }
    .searchBtn {
      position: absolute;
      right: @size-5;
      top: @size-5;
    }
  }
}

:deep(.arco-form-item-label-col) {
  padding-right: 10px !important;
}
// 表格操作
.table {
  .btnOperate {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
}
.operate {
  text-align: center;
}
</style>
